/*
@STI LICENSE
(C) 2006-2008 Universit�t Innsbruck.

This file is part of myOntology.

myOntologyis free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

myOntologyis distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with myOntology.  If not, see <http://www.gnu.org/licenses/>.

@STI LICENSE */
/**
 * 
 */
package org.myontology.specialpages;

import java.lang.reflect.Field;
import java.util.List;

import org.apache.log4j.Logger;

/**
 * @author <a href="michael.hackl@sti2.at">Michael Hackl</a>
 * Project: Myontology - www.myontology.org
 * STI
 *
 * <code>AbstractSpecialPageConfig</code> is the base implementation of 
 * <code>SpecialPageConfig</code>. 
 * select has to be overridden, sort is implemented empty
 *
 */
public abstract class AbstractSpecialPageConfig implements SpecialPageConfig {

	int pageSize=0;
	int setSize=0;
	String key;
	String label;
	
	protected Logger logger = Logger.getLogger(getClass());
	
	protected AbstractSpecialPageConfig(String label) {
		this.key = getClass().getName();
		this.label=label;
	}
	
	protected AbstractSpecialPageConfig(String key,String label) {
		this.key = key;
		this.label=label;
	}
	
	
	/**
	 * <code>select</code> executes a select on the DataSource, extracts the values
	 * needed for sorting and displaying
	 * truncation can be done via LIMIT and OFFSET statements, otherwise it is done 
	 * automagically in the AbstractSpecialPageConfig
	 * this method has no default implementation
	 * 
	 * @return the unsorted and eventually untruncated ResultList
	 */
	protected abstract List<EntryRow> select();
	
	/**
	 * <code>sort</code> sorts the resultlist before the truncating in 
	 * <code>AbstractSpecialPageConfig</code> happens
	 * The default implementation is empty
	 * @param list is the resultlist obtained by the select statement
	 */
	protected void sort(List<EntryRow> list) {
		
	}
	
	public List<EntryRow> execute() {
		List<EntryRow> resultList = select();
		sort(resultList);
		if (setSize>0 && resultList.size()>setSize) {
			resultList = resultList.subList(0, setSize);
		}
		return resultList;
	}
	
	/* (non-Javadoc)
	 * @see org.myontology.specialpages.GG#isPageable()
	 */
	public boolean isPageable() {
		return pageSize>0;
	}

	/* (non-Javadoc)
	 * @see org.myontology.specialpages.GG#getPageSize()
	 */
	public int getPageSize() {
		return pageSize;
	}

	/**
	 * sets the number of entries shown on one page, if 0 is set here, paging is disabled
	 * @param pageSize
	 */
	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	/* (non-Javadoc)
	 * @see org.myontology.specialpages.GG#getSetSize()
	 */
	public int getSetSize() {
		return setSize;
	}

	/**
	 * sets the number of entries that are returned, if 0 is returned the resultset
	 * is not truncated
	 * @param setSize
	 */
	public void setSetSize(int setSize) {
		this.setSize = setSize;
	}

	
	
	/* (non-Javadoc)
	 * @see org.myontology.specialpages.GG#getKey()
	 */
	public String getKey() {
		return key;
	}

	/**
	 * the key is used to address a Config in the ConfigRegistry, so it has to be 
	 * a unique String-Value. If only one instance of the  Config is used, the usage of the
	 * fully qualified classname is adviced.
	 * @param key
	 */
	public void setKey(String key) {
		this.key = key;
	}

	/* (non-Javadoc)
	 * @see org.myontology.specialpages.GG#getLabel()
	 */
	public String getLabel() {
		return label;
	}

	/**
	 * the label is used to display this config in a list for selection
	 * @param label
	 */
	public void setLabel(String label) {
		this.label = label;
	}
	
	public SpecialPageConfig cloneMe() {
		try {
			SpecialPageConfig c = getClass().newInstance();
			copyNonEmptyFields(this, c, getClass().getDeclaredFields(), getClass());
			return c;
		}
		catch (Exception e) {
			logger.error(e);
			return null;
		}
	}
	
	private void copyNonEmptyFields(Object src, Object dst,
			Field[] fields,Class clazz) {
		for (int i=0;i<fields.length;i++) {
			try {
				fields[i].setAccessible(true);
				Object val = fields[i].get(src);
				if (val!=null) {
					fields[i].set(dst, val);
				}
			} catch (Exception e) {
				logger.error(e);
			} 
		}
		Class parent = clazz.getSuperclass();
		if (parent!=null){
			copyNonEmptyFields(src, dst, parent.getDeclaredFields(), parent);
		}
	}
	
}
